////***************************************************************************************
//// SkinnedMeshApp.cpp by Frank Luna (C) 2015 All Rights Reserved.
////***************************************************************************************
//
//#include "../../../Common/d3dApp.h"
//#include "../../../Common/MathHelper.h"
//#include "../../../Common/UploadBuffer.h"
//#include "../../../Common/GeometryGenerator.h"
//#include "../../../Common/Camera.h"
//#include "AnimFrameResource.h"
//#include "AnimShadowMap.h"
//#include "AnimSsao.h"
//#include "SkinnedData.h"
//#include "LoadM3d.h"
//
//using Microsoft::WRL::ComPtr;
//using namespace DirectX;
//using namespace DirectX::PackedVector;
//
//const int gNumFrameResources = 3;
//
//struct SkinnedModelInstance
//{
//    SkinnedData* SkinnedInfo = nullptr;
//    std::vector<DirectX::XMFLOAT4X4> FinalTransforms;
//    std::string ClipName;
//    float TimePos = 0.0f;
//
//    // Called every frame and increments the time position, interpolates the 
//    // animations for each bone based on the current animation clip, and 
//    // generates the final transforms which are ultimately set to the effect
//    // for processing in the vertex shader.
//    void UpdateSkinnedAnimation(float dt)
//    {
//        TimePos += dt;
//
//        // Loop animation
//        if(TimePos > SkinnedInfo->GetClipEndTime(ClipName))
//            TimePos = 0.0f;
//
//        // Compute the final transforms for this time position.
//        SkinnedInfo->GetFinalTransforms(ClipName, TimePos, FinalTransforms);
//    }
//};
//
//// Lightweight structure stores parameters to draw a shape.  This will
//// vary from app-to-app.
//struct RenderItem
//{
//	RenderItem() = default;
//    RenderItem(const RenderItem& rhs) = delete;
// 
//    // World matrix of the shape that describes the object's local space
//    // relative to the world space, which defines the position, orientation,
//    // and scale of the object in the world.
//    XMFLOAT4X4 World = MathHelper::Identity4x4();
//
//	XMFLOAT4X4 TexTransform = MathHelper::Identity4x4();
//
//	// Dirty flag indicating the object data has changed and we need to update the constant buffer.
//	// Because we have an object cbuffer for each FrameResource, we have to apply the
//	// update to each FrameResource.  Thus, when we modify obect data we should set 
//	// NumFramesDirty = gNumFrameResources so that each frame resource gets the update.
//	int NumFramesDirty = gNumFrameResources;
//
//	// Index into GPU constant buffer corresponding to the ObjectCB for this render item.
//	UINT ObjCBIndex = -1;
// 
//	Material* Mat = nullptr;
//	MeshGeometry* Geo = nullptr;
//
//    // Primitive topology.
//    D3D12_PRIMITIVE_TOPOLOGY PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//
//    // DrawIndexedInstanced parameters.
//    UINT IndexCount = 0;
//    UINT StartIndexLocation = 0;
//    int BaseVertexLocation = 0;
//	
//	// Only applicable to skinned render-items.
//    UINT SkinnedCBIndex = -1;
//	
//    // nullptr if this render-item is not animated by skinned mesh.
//    SkinnedModelInstance* SkinnedModelInst = nullptr;
//};
//
//enum class RenderLayer : int
//{
//	Opaque = 0,
//    SkinnedOpaque,
//    Debug,
//	Sky,
//	Count
//};
//
//class SkinnedMeshApp : public D3DApp
//{
//public:
//    SkinnedMeshApp(HINSTANCE hInstance);
//    SkinnedMeshApp(const SkinnedMeshApp& rhs) = delete;
//    SkinnedMeshApp& operator=(const SkinnedMeshApp& rhs) = delete;
//    ~SkinnedMeshApp();
//
//    virtual bool Initialize()override;
//
//private:
//    virtual void CreateRtvAndDsvDescriptorHeaps()override;
//    virtual void OnResize()override;
//    virtual void Update(const GameTimer& gt)override;
//    virtual void Draw(const GameTimer& gt)override;
//
//    virtual void OnMouseDown(WPARAM btnState, int x, int y)override;
//    virtual void OnMouseUp(WPARAM btnState, int x, int y)override;
//    virtual void OnMouseMove(WPARAM btnState, int x, int y)override;
//
//    void OnKeyboardInput(const GameTimer& gt);
//	void AnimateMaterials(const GameTimer& gt);
//	void UpdateObjectCBs(const GameTimer& gt);
//    void UpdateSkinnedCBs(const GameTimer& gt);
//	void UpdateMaterialBuffer(const GameTimer& gt);
//    void UpdateShadowTransform(const GameTimer& gt);
//	void UpdateMainPassCB(const GameTimer& gt);
//    void UpdateShadowPassCB(const GameTimer& gt);
//    void UpdateSsaoCB(const GameTimer& gt);
//
//	void LoadTextures();
//    void BuildRootSignature();
//    void BuildSsaoRootSignature();
//	void BuildDescriptorHeaps();
//    void BuildShadersAndInputLayout();
//    void BuildShapeGeometry();
//	void LoadSkinnedModel();
//    void BuildPSOs();
//    void BuildFrameResources();
//    void BuildMaterials();
//    void BuildRenderItems();
//    void DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems);
//    void DrawSceneToShadowMap();
//	void DrawNormalsAndDepth();
//
//    CD3DX12_CPU_DESCRIPTOR_HANDLE GetCpuSrv(int index)const;
//    CD3DX12_GPU_DESCRIPTOR_HANDLE GetGpuSrv(int index)const;
//    CD3DX12_CPU_DESCRIPTOR_HANDLE GetDsv(int index)const;
//    CD3DX12_CPU_DESCRIPTOR_HANDLE GetRtv(int index)const;
//
//	std::array<const CD3DX12_STATIC_SAMPLER_DESC, 7> GetStaticSamplers();
//
//private:
//
//    std::vector<std::unique_ptr<AnimFrameResource>> mFrameResources;
//    AnimFrameResource* mCurrFrameResource = nullptr;
//    int mCurrFrameResourceIndex = 0;
//
//    ComPtr<ID3D12RootSignature> mRootSignature = nullptr;
//    ComPtr<ID3D12RootSignature> mSsaoRootSignature = nullptr;
//
//	ComPtr<ID3D12DescriptorHeap> mSrvDescriptorHeap = nullptr;
//
//	std::unordered_map<std::string, std::unique_ptr<MeshGeometry>> mGeometries;
//	std::unordered_map<std::string, std::unique_ptr<Material>> mMaterials;
//	std::unordered_map<std::string, std::unique_ptr<Texture>> mTextures;
//	std::unordered_map<std::string, ComPtr<ID3DBlob>> mShaders;
//	std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> mPSOs;
//
//    std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout;
//    std::vector<D3D12_INPUT_ELEMENT_DESC> mSkinnedInputLayout;
// 
//	// List of all the render items.
//	std::vector<std::unique_ptr<RenderItem>> mAllRitems;
//
//	// Render items divided by PSO.
//	std::vector<RenderItem*> mRitemLayer[(int)RenderLayer::Count];
//
//	UINT mSkyTexHeapIndex = 0;
//    UINT mShadowMapHeapIndex = 0;
//    UINT mSsaoHeapIndexStart = 0;
//    UINT mSsaoAmbientMapIndex = 0;
//
//    UINT mNullCubeSrvIndex = 0;
//    UINT mNullTexSrvIndex1 = 0;
//    UINT mNullTexSrvIndex2 = 0;
//
//    CD3DX12_GPU_DESCRIPTOR_HANDLE mNullSrv;
//
//    PassConstants mMainPassCB;  // index 0 of pass cbuffer.
//    PassConstants mShadowPassCB;// index 1 of pass cbuffer.
//
//    UINT mSkinnedSrvHeapStart = 0;
//    std::string mSkinnedModelFilename = "E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Models\\soldier.m3d";
//    std::unique_ptr<SkinnedModelInstance> mSkinnedModelInst; 
//    SkinnedData mSkinnedInfo;
//    std::vector<M3DLoader::Subset> mSkinnedSubsets;
//    std::vector<M3DLoader::M3dMaterial> mSkinnedMats;
//    std::vector<std::string> mSkinnedTextureNames;
//
//	Camera mCamera;
//
//    std::unique_ptr<AnimShadowMap> mShadowMap;
//
//    std::unique_ptr<AnimSsao> mSsao;
//
//    DirectX::BoundingSphere mSceneBounds;
//
//    float mLightNearZ = 0.0f;
//    float mLightFarZ = 0.0f;
//    XMFLOAT3 mLightPosW;
//    XMFLOAT4X4 mLightView = MathHelper::Identity4x4();
//    XMFLOAT4X4 mLightProj = MathHelper::Identity4x4();
//    XMFLOAT4X4 mShadowTransform = MathHelper::Identity4x4();
//
//    float mLightRotationAngle = 0.0f;
//    XMFLOAT3 mBaseLightDirections[3] = {
//        XMFLOAT3(0.57735f, -0.57735f, 0.57735f),
//        XMFLOAT3(-0.57735f, -0.57735f, 0.57735f),
//        XMFLOAT3(0.0f, -0.707f, -0.707f)
//    };
//    XMFLOAT3 mRotatedLightDirections[3];
//
//    POINT mLastMousePos;
//};
//
//int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
//    PSTR cmdLine, int showCmd)
//{
//    // Enable run-time memory check for debug builds.
//#if defined(DEBUG) | defined(_DEBUG)
//    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
//#endif
//
//    try
//    {
//        SkinnedMeshApp theApp(hInstance);
//        if(!theApp.Initialize())
//            return 0;
//
//        return theApp.Run();
//    }
//    catch(DxException& e)
//    {
//        MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
//        return 0;
//    }
//}
//
//SkinnedMeshApp::SkinnedMeshApp(HINSTANCE hInstance)
//    : D3DApp(hInstance)
//{
//    // Estimate the scene bounding sphere manually since we know how the scene was constructed.
//    // The grid is the "widest object" with a width of 20 and depth of 30.0f, and centered at
//    // the world space origin.  In general, you need to loop over every world space vertex
//    // position and compute the bounding sphere.
//    mSceneBounds.Center = XMFLOAT3(0.0f, 0.0f, 0.0f);
//    mSceneBounds.Radius = sqrtf(10.0f*10.0f + 15.0f*15.0f);
//}
//
//SkinnedMeshApp::~SkinnedMeshApp()
//{
//    if(md3dDevice != nullptr)
//        FlushCommandQueue();
//}
//
//bool SkinnedMeshApp::Initialize()
//{
//    if(!D3DApp::Initialize())
//        return false;
//
//    // Reset the command list to prep for initialization commands.
//    ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
//
//	mCamera.SetPosition(0.0f, 2.0f, -15.0f);
// 
//    mShadowMap = std::make_unique<AnimShadowMap>(md3dDevice.Get(),
//        2048, 2048);
//
//    mSsao = std::make_unique<AnimSsao>(
//        md3dDevice.Get(),
//        mCommandList.Get(),
//        mClientWidth, mClientHeight);
//
//    LoadSkinnedModel();
//	LoadTextures();
//    BuildRootSignature();
//    BuildSsaoRootSignature();
//	BuildDescriptorHeaps();
//    BuildShadersAndInputLayout();
//    BuildShapeGeometry();
//	BuildMaterials();
//    BuildRenderItems();
//    BuildFrameResources();
//    BuildPSOs();
//
//    mSsao->SetPSOs(mPSOs["ssao"].Get(), mPSOs["ssaoBlur"].Get());
//
//    // Execute the initialization commands.
//    ThrowIfFailed(mCommandList->Close());
//    ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
//    mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
//
//    // Wait until initialization is complete.
//    FlushCommandQueue();
//
//    return true;
//}
//
//void SkinnedMeshApp::CreateRtvAndDsvDescriptorHeaps()
//{
//    // Add +1 for screen normal map, +2 for ambient maps.
//    D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc;
//    rtvHeapDesc.NumDescriptors = SwapChainBufferCount + 3;
//    rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
//    rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
//    rtvHeapDesc.NodeMask = 0;
//    ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
//        &rtvHeapDesc, IID_PPV_ARGS(mRtvHeap.GetAddressOf())));
//
//    // Add +1 DSV for shadow map.
//    D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc;
//    dsvHeapDesc.NumDescriptors = 2;
//    dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
//    dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
//    dsvHeapDesc.NodeMask = 0;
//    ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
//        &dsvHeapDesc, IID_PPV_ARGS(mDsvHeap.GetAddressOf())));
//}
// 
//void SkinnedMeshApp::OnResize()
//{
//    D3DApp::OnResize();
//
//	mCamera.SetLens(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
//
//    if(mSsao != nullptr)
//    {
//        mSsao->OnResize(mClientWidth, mClientHeight);
//
//        // Resources changed, so need to rebuild descriptors.
//        mSsao->RebuildDescriptors(mDepthStencilBuffer.Get());
//    }
//}
//
//void SkinnedMeshApp::Update(const GameTimer& gt)
//{
//    OnKeyboardInput(gt);
//
//    // Cycle through the circular frame resource array.
//    mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
//    mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
//
//    // Has the GPU finished processing the commands of the current frame resource?
//    // If not, wait until the GPU has completed commands up to this fence point.
//    if(mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
//    {
//        HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
//        ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
//        WaitForSingleObject(eventHandle, INFINITE);
//        CloseHandle(eventHandle);
//    }
//
//    //
//    // Animate the lights (and hence shadows).
//    //
//
//    mLightRotationAngle += 0.1f*gt.DeltaTime();
//
//    XMMATRIX R = XMMatrixRotationY(mLightRotationAngle);
//    for(int i = 0; i < 3; ++i)
//    {
//        XMVECTOR lightDir = XMLoadFloat3(&mBaseLightDirections[i]);
//        lightDir = XMVector3TransformNormal(lightDir, R);
//        XMStoreFloat3(&mRotatedLightDirections[i], lightDir);
//    }
// 
//	AnimateMaterials(gt);
//	UpdateObjectCBs(gt);
//    UpdateSkinnedCBs(gt);
//	UpdateMaterialBuffer(gt);
//    UpdateShadowTransform(gt);
//	UpdateMainPassCB(gt);
//    UpdateShadowPassCB(gt);
//    UpdateSsaoCB(gt);
//}
//
//void SkinnedMeshApp::Draw(const GameTimer& gt)
//{
//    auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
//
//    // Reuse the memory associated with command recording.
//    // We can only reset when the associated command lists have finished execution on the GPU.
//    ThrowIfFailed(cmdListAlloc->Reset());
//
//    // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
//    // Reusing the command list reuses memory.
//    ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
//
//    ID3D12DescriptorHeap* descriptorHeaps[] = { mSrvDescriptorHeap.Get() };
//    mCommandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);
//
//    mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
//
//	//
//	// Shadow map pass.
//	//
//
//    // Bind all the materials used in this scene.  For structured buffers, we can bypass the heap and 
//    // set as a root descriptor.
//    auto matBuffer = mCurrFrameResource->MaterialBuffer->Resource();
//    mCommandList->SetGraphicsRootShaderResourceView(3, matBuffer->GetGPUVirtualAddress());
//	
//    // Bind null SRV for shadow map pass.
//    mCommandList->SetGraphicsRootDescriptorTable(4, mNullSrv);	 
//
//    // Bind all the textures used in this scene.  Observe
//    // that we only have to specify the first descriptor in the table.  
//    // The root signature knows how many descriptors are expected in the table.
//    mCommandList->SetGraphicsRootDescriptorTable(5, mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
//
//    DrawSceneToShadowMap();
//
//	//
//	// Normal/depth pass.
//	//
//	
//	DrawNormalsAndDepth();
//	
//	//
//	//
//	// 
//	
//    mCommandList->SetGraphicsRootSignature(mSsaoRootSignature.Get());
//    mSsao->ComputeSsao(mCommandList.Get(), mCurrFrameResource, 2);
//	
//	//
//	// Main rendering pass.
//	//
//	
//    mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
//
//    // Rebind state whenever graphics root signature changes.
//
//    // Bind all the materials used in this scene.  For structured buffers, we can bypass the heap and 
//    // set as a root descriptor.
//    matBuffer = mCurrFrameResource->MaterialBuffer->Resource();
//    mCommandList->SetGraphicsRootShaderResourceView(3, matBuffer->GetGPUVirtualAddress());
//
//
//    mCommandList->RSSetViewports(1, &mScreenViewport);
//    mCommandList->RSSetScissorRects(1, &mScissorRect);
//
//    // Indicate a state transition on the resource usage.
//	mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
//		D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
//
//    // Clear the back buffer and depth buffer.
//    mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr);
//    mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
//
//    // Specify the buffers we are going to render to.
//    mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
//
//	// Bind all the textures used in this scene.  Observe
//    // that we only have to specify the first descriptor in the table.  
//    // The root signature knows how many descriptors are expected in the table.
//    mCommandList->SetGraphicsRootDescriptorTable(5, mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
//	
//    auto passCB = mCurrFrameResource->PassCB->Resource();
//	mCommandList->SetGraphicsRootConstantBufferView(2, passCB->GetGPUVirtualAddress());
//
//    // Bind the sky cube map.  For our demos, we just use one "world" cube map representing the environment
//    // from far away, so all objects will use the same cube map and we only need to set it once per-frame.  
//    // If we wanted to use "local" cube maps, we would have to change them per-object, or dynamically
//    // index into an array of cube maps.
//
//    CD3DX12_GPU_DESCRIPTOR_HANDLE skyTexDescriptor(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
//    skyTexDescriptor.Offset(mSkyTexHeapIndex, mCbvSrvUavDescriptorSize);
//    mCommandList->SetGraphicsRootDescriptorTable(4, skyTexDescriptor);
//
//    mCommandList->SetPipelineState(mPSOs["opaque"].Get());
//    DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
//
//    mCommandList->SetPipelineState(mPSOs["skinnedOpaque"].Get());
//    DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::SkinnedOpaque]);
//
//    mCommandList->SetPipelineState(mPSOs["debug"].Get());
//    DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Debug]);
//
//	mCommandList->SetPipelineState(mPSOs["sky"].Get());
//	DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Sky]);
//
//    // Indicate a state transition on the resource usage.
//	mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
//		D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
//
//    // Done recording commands.
//    ThrowIfFailed(mCommandList->Close());
//
//    // Add the command list to the queue for execution.
//    ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
//    mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
//
//    // Swap the back and front buffers
//    ThrowIfFailed(mSwapChain->Present(0, 0));
//	mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;
//
//    // Advance the fence value to mark commands up to this fence point.
//    mCurrFrameResource->Fence = ++mCurrentFence;
//
//    // Add an instruction to the command queue to set a new fence point. 
//    // Because we are on the GPU timeline, the new fence point won't be 
//    // set until the GPU finishes processing all the commands prior to this Signal().
//    mCommandQueue->Signal(mFence.Get(), mCurrentFence);
//}
//
//void SkinnedMeshApp::OnMouseDown(WPARAM btnState, int x, int y)
//{
//    mLastMousePos.x = x;
//    mLastMousePos.y = y;
//
//    SetCapture(mhMainWnd);
//}
//
//void SkinnedMeshApp::OnMouseUp(WPARAM btnState, int x, int y)
//{
//    ReleaseCapture();
//}
//
//void SkinnedMeshApp::OnMouseMove(WPARAM btnState, int x, int y)
//{
//    if((btnState & MK_LBUTTON) != 0)
//    {
//		// Make each pixel correspond to a quarter of a degree.
//		float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
//		float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
//
//		mCamera.Pitch(dy);
//		mCamera.RotateY(dx);
//    }
//
//    mLastMousePos.x = x;
//    mLastMousePos.y = y;
//}
// 
//void SkinnedMeshApp::OnKeyboardInput(const GameTimer& gt)
//{
//	const float dt = gt.DeltaTime();
//
//	if(GetAsyncKeyState('W') & 0x8000)
//		mCamera.Walk(10.0f*dt);
//
//	if(GetAsyncKeyState('S') & 0x8000)
//		mCamera.Walk(-10.0f*dt);
//
//	if(GetAsyncKeyState('A') & 0x8000)
//		mCamera.Strafe(-10.0f*dt);
//
//	if(GetAsyncKeyState('D') & 0x8000)
//		mCamera.Strafe(10.0f*dt);
//
//	mCamera.UpdateViewMatrix();
//}
// 
//void SkinnedMeshApp::AnimateMaterials(const GameTimer& gt)
//{
//	
//}
//
//void SkinnedMeshApp::UpdateObjectCBs(const GameTimer& gt)
//{
//	auto currObjectCB = mCurrFrameResource->ObjectCB.get();
//	for(auto& e : mAllRitems)
//	{
//		// Only update the cbuffer data if the constants have changed.  
//		// This needs to be tracked per frame resource.
//		if(e->NumFramesDirty > 0)
//		{
//            XMMATRIX world = XMLoadFloat4x4(&e->World);
//            XMMATRIX texTransform = XMLoadFloat4x4(&e->TexTransform);
//
//            ObjectConstants objConstants;
//            XMStoreFloat4x4(&objConstants.World, XMMatrixTranspose(world));
//            XMStoreFloat4x4(&objConstants.TexTransform, XMMatrixTranspose(texTransform));
//            objConstants.MaterialIndex = e->Mat->MatCBIndex;
//
//            currObjectCB->CopyData(e->ObjCBIndex, objConstants);
//
//			// Next FrameResource need to be updated too.
//			e->NumFramesDirty--;
//		}
//	}
//}
//
//void SkinnedMeshApp::UpdateSkinnedCBs(const GameTimer& gt)
//{
//    auto currSkinnedCB = mCurrFrameResource->SkinnedCB.get();
//   
//    // We only have one skinned model being animated.
//    mSkinnedModelInst->UpdateSkinnedAnimation(gt.DeltaTime());
//        
//    SkinnedConstants skinnedConstants;
//    std::copy(
//        std::begin(mSkinnedModelInst->FinalTransforms),
//        std::end(mSkinnedModelInst->FinalTransforms),
//        &skinnedConstants.BoneTransforms[0]);
//
//    currSkinnedCB->CopyData(0, skinnedConstants);
//}
// 
//void SkinnedMeshApp::UpdateMaterialBuffer(const GameTimer& gt)
//{
//	auto currMaterialBuffer = mCurrFrameResource->MaterialBuffer.get();
//	for(auto& e : mMaterials)
//	{
//		// Only update the cbuffer data if the constants have changed.  If the cbuffer
//		// data changes, it needs to be updated for each FrameResource.
//		Material* mat = e.second.get();
//		if(mat->NumFramesDirty > 0)
//		{
//			XMMATRIX matTransform = XMLoadFloat4x4(&mat->MatTransform);
//
//			MaterialData matData;
//			matData.DiffuseAlbedo = mat->DiffuseAlbedo;
//			matData.FresnelR0 = mat->FresnelR0;
//			matData.Roughness = mat->Roughness;
//			XMStoreFloat4x4(&matData.MatTransform, XMMatrixTranspose(matTransform));
//			matData.DiffuseMapIndex = mat->DiffuseSrvHeapIndex;
//			matData.NormalMapIndex = mat->NormalSrvHeapIndex;
//
//			currMaterialBuffer->CopyData(mat->MatCBIndex, matData);
//
//			// Next FrameResource need to be updated too.
//			mat->NumFramesDirty--;
//		}
//	}
//}
//
//void SkinnedMeshApp::UpdateShadowTransform(const GameTimer& gt)
//{
//    // Only the first "main" light casts a shadow.
//    XMVECTOR lightDir = XMLoadFloat3(&mRotatedLightDirections[0]);
//    XMVECTOR lightPos = -2.0f*mSceneBounds.Radius*lightDir;
//    XMVECTOR targetPos = XMLoadFloat3(&mSceneBounds.Center);
//    XMVECTOR lightUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
//    XMMATRIX lightView = XMMatrixLookAtLH(lightPos, targetPos, lightUp);
//
//    XMStoreFloat3(&mLightPosW, lightPos);
//
//    // Transform bounding sphere to light space.
//    XMFLOAT3 sphereCenterLS;
//    XMStoreFloat3(&sphereCenterLS, XMVector3TransformCoord(targetPos, lightView));
//
//    // Ortho frustum in light space encloses scene.
//    float l = sphereCenterLS.x - mSceneBounds.Radius;
//    float b = sphereCenterLS.y - mSceneBounds.Radius;
//    float n = sphereCenterLS.z - mSceneBounds.Radius;
//    float r = sphereCenterLS.x + mSceneBounds.Radius;
//    float t = sphereCenterLS.y + mSceneBounds.Radius;
//    float f = sphereCenterLS.z + mSceneBounds.Radius;
//
//    mLightNearZ = n;
//    mLightFarZ = f;
//    XMMATRIX lightProj = XMMatrixOrthographicOffCenterLH(l, r, b, t, n, f);
//
//    // Transform NDC space [-1,+1]^2 to texture space [0,1]^2
//    XMMATRIX T(
//        0.5f, 0.0f, 0.0f, 0.0f,
//        0.0f, -0.5f, 0.0f, 0.0f,
//        0.0f, 0.0f, 1.0f, 0.0f,
//        0.5f, 0.5f, 0.0f, 1.0f);
//
//    XMMATRIX S = lightView*lightProj*T;
//    XMStoreFloat4x4(&mLightView, lightView);
//    XMStoreFloat4x4(&mLightProj, lightProj);
//    XMStoreFloat4x4(&mShadowTransform, S);
//}
//
//void SkinnedMeshApp::UpdateMainPassCB(const GameTimer& gt)
//{
//	XMMATRIX view = mCamera.GetView();
//	XMMATRIX proj = mCamera.GetProj();
//
//	XMMATRIX viewProj = XMMatrixMultiply(view, proj);
//	XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
//	XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
//	XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
//
//    // Transform NDC space [-1,+1]^2 to texture space [0,1]^2
//    XMMATRIX T(
//        0.5f, 0.0f, 0.0f, 0.0f,
//        0.0f, -0.5f, 0.0f, 0.0f,
//        0.0f, 0.0f, 1.0f, 0.0f,
//        0.5f, 0.5f, 0.0f, 1.0f);
//
//    XMMATRIX viewProjTex = XMMatrixMultiply(viewProj, T);
//    XMMATRIX shadowTransform = XMLoadFloat4x4(&mShadowTransform);
//
//	XMStoreFloat4x4(&mMainPassCB.View, XMMatrixTranspose(view));
//	XMStoreFloat4x4(&mMainPassCB.InvView, XMMatrixTranspose(invView));
//	XMStoreFloat4x4(&mMainPassCB.Proj, XMMatrixTranspose(proj));
//	XMStoreFloat4x4(&mMainPassCB.InvProj, XMMatrixTranspose(invProj));
//	XMStoreFloat4x4(&mMainPassCB.ViewProj, XMMatrixTranspose(viewProj));
//	XMStoreFloat4x4(&mMainPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
//    XMStoreFloat4x4(&mMainPassCB.ViewProjTex, XMMatrixTranspose(viewProjTex));
//    XMStoreFloat4x4(&mMainPassCB.ShadowTransform, XMMatrixTranspose(shadowTransform));
//	mMainPassCB.EyePosW = mCamera.GetPosition3f();
//	mMainPassCB.RenderTargetSize = XMFLOAT2((float)mClientWidth, (float)mClientHeight);
//	mMainPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / mClientWidth, 1.0f / mClientHeight);
//	mMainPassCB.NearZ = 1.0f;
//	mMainPassCB.FarZ = 1000.0f;
//	mMainPassCB.TotalTime = gt.TotalTime();
//	mMainPassCB.DeltaTime = gt.DeltaTime();
//	mMainPassCB.AmbientLight = { 0.25f, 0.25f, 0.35f, 1.0f };
//	mMainPassCB.Lights[0].Direction = mRotatedLightDirections[0];
//	mMainPassCB.Lights[0].Strength = { 0.9f, 0.9f, 0.7f };
//	mMainPassCB.Lights[1].Direction = mRotatedLightDirections[1];
//	mMainPassCB.Lights[1].Strength = { 0.4f, 0.4f, 0.4f };
//	mMainPassCB.Lights[2].Direction = mRotatedLightDirections[2];
//	mMainPassCB.Lights[2].Strength = { 0.2f, 0.2f, 0.2f };
// 
//	auto currPassCB = mCurrFrameResource->PassCB.get();
//	currPassCB->CopyData(0, mMainPassCB);
//}
//
//void SkinnedMeshApp::UpdateShadowPassCB(const GameTimer& gt)
//{
//    XMMATRIX view = XMLoadFloat4x4(&mLightView);
//    XMMATRIX proj = XMLoadFloat4x4(&mLightProj);
//
//    XMMATRIX viewProj = XMMatrixMultiply(view, proj);
//    XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
//    XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
//    XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
//
//    UINT w = mShadowMap->Width();
//    UINT h = mShadowMap->Height();
//
//    XMStoreFloat4x4(&mShadowPassCB.View, XMMatrixTranspose(view));
//    XMStoreFloat4x4(&mShadowPassCB.InvView, XMMatrixTranspose(invView));
//    XMStoreFloat4x4(&mShadowPassCB.Proj, XMMatrixTranspose(proj));
//    XMStoreFloat4x4(&mShadowPassCB.InvProj, XMMatrixTranspose(invProj));
//    XMStoreFloat4x4(&mShadowPassCB.ViewProj, XMMatrixTranspose(viewProj));
//    XMStoreFloat4x4(&mShadowPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
//    mShadowPassCB.EyePosW = mLightPosW;
//    mShadowPassCB.RenderTargetSize = XMFLOAT2((float)w, (float)h);
//    mShadowPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / w, 1.0f / h);
//    mShadowPassCB.NearZ = mLightNearZ;
//    mShadowPassCB.FarZ = mLightFarZ;
//
//    auto currPassCB = mCurrFrameResource->PassCB.get();
//    currPassCB->CopyData(1, mShadowPassCB);
//}
//
//void SkinnedMeshApp::UpdateSsaoCB(const GameTimer& gt)
//{
//    SsaoConstants ssaoCB;
//
//    XMMATRIX P = mCamera.GetProj();
//
//    // Transform NDC space [-1,+1]^2 to texture space [0,1]^2
//    XMMATRIX T(
//        0.5f, 0.0f, 0.0f, 0.0f,
//        0.0f, -0.5f, 0.0f, 0.0f,
//        0.0f, 0.0f, 1.0f, 0.0f,
//        0.5f, 0.5f, 0.0f, 1.0f);
//
//    ssaoCB.Proj    = mMainPassCB.Proj;
//    ssaoCB.InvProj = mMainPassCB.InvProj;
//    XMStoreFloat4x4(&ssaoCB.ProjTex, XMMatrixTranspose(P*T));
//
//    mSsao->GetOffsetVectors(ssaoCB.OffsetVectors);
//
//    auto blurWeights = mSsao->CalcGaussWeights(2.5f);
//    ssaoCB.BlurWeights[0] = XMFLOAT4(&blurWeights[0]);
//    ssaoCB.BlurWeights[1] = XMFLOAT4(&blurWeights[4]);
//    ssaoCB.BlurWeights[2] = XMFLOAT4(&blurWeights[8]);
//
//    ssaoCB.InvRenderTargetSize = XMFLOAT2(1.0f / mSsao->SsaoMapWidth(), 1.0f / mSsao->SsaoMapHeight());
//
//    // Coordinates given in view space.
//    ssaoCB.OcclusionRadius = 0.5f;
//    ssaoCB.OcclusionFadeStart = 0.2f;
//    ssaoCB.OcclusionFadeEnd = 2.0f;
//    ssaoCB.SurfaceEpsilon = 0.05f;
//
//    auto currSsaoCB = mCurrFrameResource->SsaoCB.get();
//    currSsaoCB->CopyData(0, ssaoCB);
//}
//
//void SkinnedMeshApp::LoadTextures()
//{
//	std::vector<std::string> texNames = 
//	{
//		"bricksDiffuseMap",
//		"bricksNormalMap",
//		"tileDiffuseMap",
//		"tileNormalMap",
//		"defaultDiffuseMap",
//		"defaultNormalMap",
//		"skyCubeMap"
//	};
//	
//	std::vector<std::wstring> texFilenames = 
//	{
//		L"E:/DX12Book/DX12LearnProject/DX12Learn/Textures/bricks2.dds",
//		L"E:/DX12Book/DX12LearnProject/DX12Learn/Textures/bricks2_nmap.dds",
//		L"E:/DX12Book/DX12LearnProject/DX12Learn/Textures/tile.dds",
//		L"E:/DX12Book/DX12LearnProject/DX12Learn/Textures/tile_nmap.dds",
//		L"E:/DX12Book/DX12LearnProject/DX12Learn/Textures/white1x1.dds",
//		L"E:/DX12Book/DX12LearnProject/DX12Learn/Textures/default_nmap.dds",
//		L"E:/DX12Book/DX12LearnProject/DX12Learn/Textures/desertcube1024.dds"
//	};
//
//    // Add skinned model textures to list so we can reference by name later.
//    for(UINT i = 0; i < mSkinnedMats.size(); ++i)
//    {
//        std::string diffuseName = mSkinnedMats[i].DiffuseMapName;
//        std::string normalName = mSkinnedMats[i].NormalMapName;
//
//        std::wstring diffuseFilename = L"E:/DX12Book/DX12LearnProject/DX12Learn/Textures/" + AnsiToWString(diffuseName);
//        std::wstring normalFilename = L"E:/DX12Book/DX12LearnProject/DX12Learn/Textures/" + AnsiToWString(normalName);
//
//        // strip off extension
//        diffuseName = diffuseName.substr(0, diffuseName.find_last_of("."));
//        normalName = normalName.substr(0, normalName.find_last_of("."));
//
//        mSkinnedTextureNames.push_back(diffuseName);
//        texNames.push_back(diffuseName);
//        texFilenames.push_back(diffuseFilename);
//
//        mSkinnedTextureNames.push_back(normalName);
//        texNames.push_back(normalName);
//        texFilenames.push_back(normalFilename);
//    }
//	
//	for(int i = 0; i < (int)texNames.size(); ++i)
//	{
//        // Don't create duplicates.
//        if(mTextures.find(texNames[i]) == std::end(mTextures))
//        {
//            auto texMap = std::make_unique<Texture>();
//            texMap->Name = texNames[i];
//            texMap->Filename = texFilenames[i];
//            ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
//                mCommandList.Get(), texMap->Filename.c_str(),
//                texMap->Resource, texMap->UploadHeap));
//
//            mTextures[texMap->Name] = std::move(texMap);
//        }
//	}		
//}
//
//void SkinnedMeshApp::BuildRootSignature()
//{
//	CD3DX12_DESCRIPTOR_RANGE texTable0;
//	texTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 3, 0, 0);
//
//	CD3DX12_DESCRIPTOR_RANGE texTable1;
//	texTable1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 48, 3, 0);
//
//    // Root parameter can be a table, root descriptor or root constants.
//    CD3DX12_ROOT_PARAMETER slotRootParameter[6];
//
//	// Perfomance TIP: Order from most frequent to least frequent.
//    slotRootParameter[0].InitAsConstantBufferView(0);
//    slotRootParameter[1].InitAsConstantBufferView(1);
//    slotRootParameter[2].InitAsConstantBufferView(2);
//    slotRootParameter[3].InitAsShaderResourceView(0, 1);
//	slotRootParameter[4].InitAsDescriptorTable(1, &texTable0, D3D12_SHADER_VISIBILITY_PIXEL);
//	slotRootParameter[5].InitAsDescriptorTable(1, &texTable1, D3D12_SHADER_VISIBILITY_PIXEL);
//
//	auto staticSamplers = GetStaticSamplers();
//
//    // A root signature is an array of root parameters.
//	CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(6, slotRootParameter,
//		(UINT)staticSamplers.size(), staticSamplers.data(),
//		D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
//
//    // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
//    ComPtr<ID3DBlob> serializedRootSig = nullptr;
//    ComPtr<ID3DBlob> errorBlob = nullptr;
//    HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
//        serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
//
//    if(errorBlob != nullptr)
//    {
//        ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
//    }
//    ThrowIfFailed(hr);
//
//    ThrowIfFailed(md3dDevice->CreateRootSignature(
//		0,
//        serializedRootSig->GetBufferPointer(),
//        serializedRootSig->GetBufferSize(),
//        IID_PPV_ARGS(mRootSignature.GetAddressOf())));
//}
//
//void SkinnedMeshApp::BuildSsaoRootSignature()
//{
//    CD3DX12_DESCRIPTOR_RANGE texTable0;
//    texTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 2, 0, 0);
//
//    CD3DX12_DESCRIPTOR_RANGE texTable1;
//    texTable1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 2, 0);
//
//    // Root parameter can be a table, root descriptor or root constants.
//    CD3DX12_ROOT_PARAMETER slotRootParameter[4];
//
//    // Perfomance TIP: Order from most frequent to least frequent.
//    slotRootParameter[0].InitAsConstantBufferView(0);
//    slotRootParameter[1].InitAsConstants(1, 1);
//    slotRootParameter[2].InitAsDescriptorTable(1, &texTable0, D3D12_SHADER_VISIBILITY_PIXEL);
//    slotRootParameter[3].InitAsDescriptorTable(1, &texTable1, D3D12_SHADER_VISIBILITY_PIXEL);
//
//    const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
//        0, // shaderRegister
//        D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
//        D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
//        D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
//        D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
//
//    const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
//        1, // shaderRegister
//        D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
//        D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
//        D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
//        D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
//
//    const CD3DX12_STATIC_SAMPLER_DESC depthMapSam(
//        2, // shaderRegister
//        D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
//        D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressU
//        D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressV
//        D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressW
//        0.0f,
//        0,
//        D3D12_COMPARISON_FUNC_LESS_EQUAL,
//        D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE); 
//
//    const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
//        3, // shaderRegister
//        D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
//        D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
//        D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
//        D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
//
//    std::array<CD3DX12_STATIC_SAMPLER_DESC, 4> staticSamplers =
//    {
//        pointClamp, linearClamp, depthMapSam, linearWrap
//    };
//
//    // A root signature is an array of root parameters.
//    CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(4, slotRootParameter,
//        (UINT)staticSamplers.size(), staticSamplers.data(),
//        D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
//
//    // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
//    ComPtr<ID3DBlob> serializedRootSig = nullptr;
//    ComPtr<ID3DBlob> errorBlob = nullptr;
//    HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
//        serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
//
//    if(errorBlob != nullptr)
//    {
//        ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
//    }
//    ThrowIfFailed(hr);
//
//    ThrowIfFailed(md3dDevice->CreateRootSignature(
//        0,
//        serializedRootSig->GetBufferPointer(),
//        serializedRootSig->GetBufferSize(),
//        IID_PPV_ARGS(mSsaoRootSignature.GetAddressOf())));
//}
//
//void SkinnedMeshApp::BuildDescriptorHeaps()
//{
//	//
//	// Create the SRV heap.
//	//
//	D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
//	srvHeapDesc.NumDescriptors = 64;
//	srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
//	srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
//	ThrowIfFailed(md3dDevice->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&mSrvDescriptorHeap)));
//
//	//
//	// Fill out the heap with actual descriptors.
//	//
//	CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
//
//	std::vector<ComPtr<ID3D12Resource>> tex2DList = 
//	{
//		mTextures["bricksDiffuseMap"]->Resource,
//		mTextures["bricksNormalMap"]->Resource,
//		mTextures["tileDiffuseMap"]->Resource,
//		mTextures["tileNormalMap"]->Resource,
//		mTextures["defaultDiffuseMap"]->Resource,
//		mTextures["defaultNormalMap"]->Resource
//	};
//
//    mSkinnedSrvHeapStart = (UINT)tex2DList.size();
//
//    for(UINT i = 0; i < (UINT)mSkinnedTextureNames.size(); ++i)
//    {
//        auto texResource = mTextures[mSkinnedTextureNames[i]]->Resource;
//        assert(texResource != nullptr);
//        tex2DList.push_back(texResource);
//    }
//	
//
//	auto skyCubeMap = mTextures["skyCubeMap"]->Resource;
//
//	D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
//	srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
//	srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
//	srvDesc.Texture2D.MostDetailedMip = 0;
//	srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
//	
//	for(UINT i = 0; i < (UINT)tex2DList.size(); ++i)
//	{
//		srvDesc.Format = tex2DList[i]->GetDesc().Format;
//		srvDesc.Texture2D.MipLevels = tex2DList[i]->GetDesc().MipLevels;
//		md3dDevice->CreateShaderResourceView(tex2DList[i].Get(), &srvDesc, hDescriptor);
//
//		// next descriptor
//		hDescriptor.Offset(1, mCbvSrvUavDescriptorSize);
//	}
//	
//	srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
//	srvDesc.TextureCube.MostDetailedMip = 0;
//	srvDesc.TextureCube.MipLevels = skyCubeMap->GetDesc().MipLevels;
//	srvDesc.TextureCube.ResourceMinLODClamp = 0.0f;
//	srvDesc.Format = skyCubeMap->GetDesc().Format;
//	md3dDevice->CreateShaderResourceView(skyCubeMap.Get(), &srvDesc, hDescriptor);
//	
//	mSkyTexHeapIndex = (UINT)tex2DList.size();
//    mShadowMapHeapIndex = mSkyTexHeapIndex + 1;
//    mSsaoHeapIndexStart = mShadowMapHeapIndex + 1;
//    mSsaoAmbientMapIndex = mSsaoHeapIndexStart + 3;
//    mNullCubeSrvIndex = mSsaoHeapIndexStart + 5;
//    mNullTexSrvIndex1 = mNullCubeSrvIndex + 1;
//    mNullTexSrvIndex2 = mNullTexSrvIndex1 + 1;
//
//    auto nullSrv = GetCpuSrv(mNullCubeSrvIndex);
//    mNullSrv = GetGpuSrv(mNullCubeSrvIndex);
//
//    md3dDevice->CreateShaderResourceView(nullptr, &srvDesc, nullSrv);
//    nullSrv.Offset(1, mCbvSrvUavDescriptorSize);
//
//    srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
//    srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
//    srvDesc.Texture2D.MostDetailedMip = 0;
//    srvDesc.Texture2D.MipLevels = 1;
//    srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
//    md3dDevice->CreateShaderResourceView(nullptr, &srvDesc, nullSrv);
//
//    nullSrv.Offset(1, mCbvSrvUavDescriptorSize);
//    md3dDevice->CreateShaderResourceView(nullptr, &srvDesc, nullSrv);
//
//    mShadowMap->BuildDescriptors(
//        GetCpuSrv(mShadowMapHeapIndex),
//        GetGpuSrv(mShadowMapHeapIndex),
//        GetDsv(1));
//
//    mSsao->BuildDescriptors(
//        mDepthStencilBuffer.Get(),
//        GetCpuSrv(mSsaoHeapIndexStart),
//        GetGpuSrv(mSsaoHeapIndexStart),
//        GetRtv(SwapChainBufferCount),
//        mCbvSrvUavDescriptorSize,
//        mRtvDescriptorSize);
//}
//
//void SkinnedMeshApp::BuildShadersAndInputLayout()
//{
//	const D3D_SHADER_MACRO alphaTestDefines[] =
//	{
//		"ALPHA_TEST", "1",
//		NULL, NULL
//	};
//
//    const D3D_SHADER_MACRO skinnedDefines[] =
//    {
//        "SKINNED", "1",
//        NULL, NULL
//    };
//
//	mShaders["standardVS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\Default.hlsl", nullptr, "VS", "vs_5_1");
//    mShaders["skinnedVS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\Default.hlsl", skinnedDefines, "VS", "vs_5_1");
//	mShaders["opaquePS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\Default.hlsl", nullptr, "PS", "ps_5_1");
//
//    mShaders["shadowVS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\Shadows.hlsl", nullptr, "VS", "vs_5_1");
//    mShaders["skinnedShadowVS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\Shadows.hlsl", skinnedDefines, "VS", "vs_5_1");
//    mShaders["shadowOpaquePS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\Shadows.hlsl", nullptr, "PS", "ps_5_1");
//    mShaders["shadowAlphaTestedPS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\Shadows.hlsl", alphaTestDefines, "PS", "ps_5_1");
//	
//    mShaders["debugVS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\ShadowDebug.hlsl", nullptr, "VS", "vs_5_1");
//    mShaders["debugPS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\ShadowDebug.hlsl", nullptr, "PS", "ps_5_1");
//
//    mShaders["drawNormalsVS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\DrawNormals.hlsl", nullptr, "VS", "vs_5_1");
//    mShaders["skinnedDrawNormalsVS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\DrawNormals.hlsl", skinnedDefines, "VS", "vs_5_1");
//    mShaders["drawNormalsPS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\DrawNormals.hlsl", nullptr, "PS", "ps_5_1");
//
//    mShaders["ssaoVS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\Ssao.hlsl", nullptr, "VS", "vs_5_1");
//    mShaders["ssaoPS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\Ssao.hlsl", nullptr, "PS", "ps_5_1");
//
//    mShaders["ssaoBlurVS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\SsaoBlur.hlsl", nullptr, "VS", "vs_5_1");
//    mShaders["ssaoBlurPS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\SsaoBlur.hlsl", nullptr, "PS", "ps_5_1");
//
//	mShaders["skyVS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\Sky.hlsl", nullptr, "VS", "vs_5_1");
//	mShaders["skyPS"] = d3dUtil::CompileShader(L"E:\\DX12Book\\DX12LearnProject\\DX12Learn\\LearnDemo\\Chapter 23 Character Animation\\SkinnedMesh\\Shaders\\Sky.hlsl", nullptr, "PS", "ps_5_1");
//
//    mInputLayout =
//    {
//        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
//        { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
//		{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
//		{ "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 32, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
//    };
//
//    mSkinnedInputLayout =
//    {
//        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
//        { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
//        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
//        { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 32, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
//        { "WEIGHTS", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 44, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
//        { "BONEINDICES", 0, DXGI_FORMAT_R8G8B8A8_UINT, 0, 56, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
//    };
//}
//
//void SkinnedMeshApp::BuildShapeGeometry()
//{
//    GeometryGenerator geoGen;
//	GeometryGenerator::MeshData box = geoGen.CreateBox(1.0f, 1.0f, 1.0f, 3);
//	GeometryGenerator::MeshData grid = geoGen.CreateGrid(20.0f, 30.0f, 60, 40);
//	GeometryGenerator::MeshData sphere = geoGen.CreateSphere(0.5f, 20, 20);
//	GeometryGenerator::MeshData cylinder = geoGen.CreateCylinder(0.5f, 0.3f, 3.0f, 20, 20);
//    GeometryGenerator::MeshData quad = geoGen.CreateQuad(0.0f, 0.0f, 1.0f, 1.0f, 0.0f);
//    
//	//
//	// We are concatenating all the geometry into one big vertex/index buffer.  So
//	// define the regions in the buffer each submesh covers.
//	//
//
//	// Cache the vertex offsets to each object in the concatenated vertex buffer.
//	UINT boxVertexOffset = 0;
//	UINT gridVertexOffset = (UINT)box.Vertices.size();
//	UINT sphereVertexOffset = gridVertexOffset + (UINT)grid.Vertices.size();
//	UINT cylinderVertexOffset = sphereVertexOffset + (UINT)sphere.Vertices.size();
//    UINT quadVertexOffset = cylinderVertexOffset + (UINT)cylinder.Vertices.size();
//
//	// Cache the starting index for each object in the concatenated index buffer.
//	UINT boxIndexOffset = 0;
//	UINT gridIndexOffset = (UINT)box.Indices32.size();
//	UINT sphereIndexOffset = gridIndexOffset + (UINT)grid.Indices32.size();
//	UINT cylinderIndexOffset = sphereIndexOffset + (UINT)sphere.Indices32.size();
//    UINT quadIndexOffset = cylinderIndexOffset + (UINT)cylinder.Indices32.size();
//
//	SubmeshGeometry boxSubmesh;
//	boxSubmesh.IndexCount = (UINT)box.Indices32.size();
//	boxSubmesh.StartIndexLocation = boxIndexOffset;
//	boxSubmesh.BaseVertexLocation = boxVertexOffset;
//
//	SubmeshGeometry gridSubmesh;
//	gridSubmesh.IndexCount = (UINT)grid.Indices32.size();
//	gridSubmesh.StartIndexLocation = gridIndexOffset;
//	gridSubmesh.BaseVertexLocation = gridVertexOffset;
//
//	SubmeshGeometry sphereSubmesh;
//	sphereSubmesh.IndexCount = (UINT)sphere.Indices32.size();
//	sphereSubmesh.StartIndexLocation = sphereIndexOffset;
//	sphereSubmesh.BaseVertexLocation = sphereVertexOffset;
//
//	SubmeshGeometry cylinderSubmesh;
//	cylinderSubmesh.IndexCount = (UINT)cylinder.Indices32.size();
//	cylinderSubmesh.StartIndexLocation = cylinderIndexOffset;
//	cylinderSubmesh.BaseVertexLocation = cylinderVertexOffset;
//
//    SubmeshGeometry quadSubmesh;
//    quadSubmesh.IndexCount = (UINT)quad.Indices32.size();
//    quadSubmesh.StartIndexLocation = quadIndexOffset;
//    quadSubmesh.BaseVertexLocation = quadVertexOffset;
//
//	//
//	// Extract the vertex elements we are interested in and pack the
//	// vertices of all the meshes into one vertex buffer.
//	//
//
//	auto totalVertexCount =
//		box.Vertices.size() +
//		grid.Vertices.size() +
//		sphere.Vertices.size() +
//		cylinder.Vertices.size() + 
//        quad.Vertices.size();
//
//	std::vector<Vertex> vertices(totalVertexCount);
//
//	UINT k = 0;
//	for(size_t i = 0; i < box.Vertices.size(); ++i, ++k)
//	{
//		vertices[k].Pos = box.Vertices[i].Position;
//		vertices[k].Normal = box.Vertices[i].Normal;
//		vertices[k].TexC = box.Vertices[i].TexC;
//		vertices[k].TangentU = box.Vertices[i].TangentU;
//	}
//
//	for(size_t i = 0; i < grid.Vertices.size(); ++i, ++k)
//	{
//		vertices[k].Pos = grid.Vertices[i].Position;
//		vertices[k].Normal = grid.Vertices[i].Normal;
//		vertices[k].TexC = grid.Vertices[i].TexC;
//		vertices[k].TangentU = grid.Vertices[i].TangentU;
//	}
//
//	for(size_t i = 0; i < sphere.Vertices.size(); ++i, ++k)
//	{
//		vertices[k].Pos = sphere.Vertices[i].Position;
//		vertices[k].Normal = sphere.Vertices[i].Normal;
//		vertices[k].TexC = sphere.Vertices[i].TexC;
//		vertices[k].TangentU = sphere.Vertices[i].TangentU;
//	}
//
//	for(size_t i = 0; i < cylinder.Vertices.size(); ++i, ++k)
//	{
//		vertices[k].Pos = cylinder.Vertices[i].Position;
//		vertices[k].Normal = cylinder.Vertices[i].Normal;
//		vertices[k].TexC = cylinder.Vertices[i].TexC;
//		vertices[k].TangentU = cylinder.Vertices[i].TangentU;
//	}
//
//    for(int i = 0; i < quad.Vertices.size(); ++i, ++k)
//    {
//        vertices[k].Pos = quad.Vertices[i].Position;
//        vertices[k].Normal = quad.Vertices[i].Normal;
//        vertices[k].TexC = quad.Vertices[i].TexC;
//        vertices[k].TangentU = quad.Vertices[i].TangentU;
//    }
//
//	std::vector<std::uint16_t> indices;
//	indices.insert(indices.end(), std::begin(box.GetIndices16()), std::end(box.GetIndices16()));
//	indices.insert(indices.end(), std::begin(grid.GetIndices16()), std::end(grid.GetIndices16()));
//	indices.insert(indices.end(), std::begin(sphere.GetIndices16()), std::end(sphere.GetIndices16()));
//	indices.insert(indices.end(), std::begin(cylinder.GetIndices16()), std::end(cylinder.GetIndices16()));
//    indices.insert(indices.end(), std::begin(quad.GetIndices16()), std::end(quad.GetIndices16()));
//
//    const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
//    const UINT ibByteSize = (UINT)indices.size()  * sizeof(std::uint16_t);
//
//	auto geo = std::make_unique<MeshGeometry>();
//	geo->Name = "shapeGeo";
//
//	ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
//	CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
//
//	ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
//	CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
//
//	geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
//		mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
//
//	geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
//		mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
//
//	geo->VertexByteStride = sizeof(Vertex);
//	geo->VertexBufferByteSize = vbByteSize;
//	geo->IndexFormat = DXGI_FORMAT_R16_UINT;
//	geo->IndexBufferByteSize = ibByteSize;
//
//	geo->DrawArgs["box"] = boxSubmesh;
//	geo->DrawArgs["grid"] = gridSubmesh;
//	geo->DrawArgs["sphere"] = sphereSubmesh;
//	geo->DrawArgs["cylinder"] = cylinderSubmesh;
//    geo->DrawArgs["quad"] = quadSubmesh;
//
//	mGeometries[geo->Name] = std::move(geo);
//}
//
//void SkinnedMeshApp::LoadSkinnedModel()
//{
//	std::vector<M3DLoader::SkinnedVertex> vertices;
//	std::vector<std::uint16_t> indices;	
// 
//	M3DLoader m3dLoader;
//	m3dLoader.LoadM3d(mSkinnedModelFilename, vertices, indices, 
//        mSkinnedSubsets, mSkinnedMats, mSkinnedInfo);
//
//    mSkinnedModelInst = std::make_unique<SkinnedModelInstance>();
//    mSkinnedModelInst->SkinnedInfo = &mSkinnedInfo;
//    mSkinnedModelInst->FinalTransforms.resize(mSkinnedInfo.BoneCount());
//    mSkinnedModelInst->ClipName = "Take1";
//    mSkinnedModelInst->TimePos = 0.0f;
// 
//	const UINT vbByteSize = (UINT)vertices.size() * sizeof(SkinnedVertex);
//    const UINT ibByteSize = (UINT)indices.size()  * sizeof(std::uint16_t);
//
//	auto geo = std::make_unique<MeshGeometry>();
//	geo->Name = mSkinnedModelFilename;
//
//	ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
//	CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
//
//	ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
//	CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
//
//	geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
//		mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
//
//	geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
//		mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
//
//	geo->VertexByteStride = sizeof(SkinnedVertex);
//	geo->VertexBufferByteSize = vbByteSize;
//	geo->IndexFormat = DXGI_FORMAT_R16_UINT;
//	geo->IndexBufferByteSize = ibByteSize;
//
//	for(UINT i = 0; i < (UINT)mSkinnedSubsets.size(); ++i)
//	{
//		SubmeshGeometry submesh;
//		std::string name = "sm_" + std::to_string(i);
//		
//        submesh.IndexCount = (UINT)mSkinnedSubsets[i].FaceCount * 3;
//        submesh.StartIndexLocation = mSkinnedSubsets[i].FaceStart * 3;
//        submesh.BaseVertexLocation = 0;
//
//		geo->DrawArgs[name] = submesh;
//	}
//
//	mGeometries[geo->Name] = std::move(geo);
//}
//
//void SkinnedMeshApp::BuildPSOs()
//{
//    D3D12_GRAPHICS_PIPELINE_STATE_DESC opaquePsoDesc;
//
//	//
//	// PSO for opaque objects.
//	//
//    ZeroMemory(&opaquePsoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
//	opaquePsoDesc.InputLayout = { mInputLayout.data(), (UINT)mInputLayout.size() };
//	opaquePsoDesc.pRootSignature = mRootSignature.Get();
//	opaquePsoDesc.VS = 
//	{ 
//		reinterpret_cast<BYTE*>(mShaders["standardVS"]->GetBufferPointer()), 
//		mShaders["standardVS"]->GetBufferSize()
//	};
//	opaquePsoDesc.PS = 
//	{ 
//		reinterpret_cast<BYTE*>(mShaders["opaquePS"]->GetBufferPointer()),
//		mShaders["opaquePS"]->GetBufferSize()
//	};
//	opaquePsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
//	opaquePsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
//	opaquePsoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
//	opaquePsoDesc.SampleMask = UINT_MAX;
//	opaquePsoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
//	opaquePsoDesc.NumRenderTargets = 1;
//	opaquePsoDesc.RTVFormats[0] = mBackBufferFormat;
//	opaquePsoDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;
//	opaquePsoDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
//	opaquePsoDesc.DSVFormat = mDepthStencilFormat;
//    ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&opaquePsoDesc, IID_PPV_ARGS(&mPSOs["opaque"])));
//
//    //
//    // PSO for skinned pass.
//    //
//    D3D12_GRAPHICS_PIPELINE_STATE_DESC skinnedOpaquePsoDesc = opaquePsoDesc;
//    skinnedOpaquePsoDesc.InputLayout = { mSkinnedInputLayout.data(), (UINT)mSkinnedInputLayout.size() };
//    skinnedOpaquePsoDesc.VS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["skinnedVS"]->GetBufferPointer()),
//        mShaders["skinnedVS"]->GetBufferSize()
//    };
//    skinnedOpaquePsoDesc.PS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["opaquePS"]->GetBufferPointer()),
//        mShaders["opaquePS"]->GetBufferSize()
//    };
//    ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&skinnedOpaquePsoDesc, IID_PPV_ARGS(&mPSOs["skinnedOpaque"])));
//
//    //
//    // PSO for shadow map pass.
//    //
//    D3D12_GRAPHICS_PIPELINE_STATE_DESC smapPsoDesc = opaquePsoDesc;
//    smapPsoDesc.RasterizerState.DepthBias = 100000;
//    smapPsoDesc.RasterizerState.DepthBiasClamp = 0.0f;
//    smapPsoDesc.RasterizerState.SlopeScaledDepthBias = 1.0f;
//    smapPsoDesc.pRootSignature = mRootSignature.Get();
//    smapPsoDesc.VS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["shadowVS"]->GetBufferPointer()),
//        mShaders["shadowVS"]->GetBufferSize()
//    };
//    smapPsoDesc.PS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["shadowOpaquePS"]->GetBufferPointer()),
//        mShaders["shadowOpaquePS"]->GetBufferSize()
//    };
//    
//    // Shadow map pass does not have a render target.
//    smapPsoDesc.RTVFormats[0] = DXGI_FORMAT_UNKNOWN;
//    smapPsoDesc.NumRenderTargets = 0;
//    ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&smapPsoDesc, IID_PPV_ARGS(&mPSOs["shadow_opaque"])));
//
//    D3D12_GRAPHICS_PIPELINE_STATE_DESC skinnedSmapPsoDesc = smapPsoDesc;
//    skinnedSmapPsoDesc.InputLayout = { mSkinnedInputLayout.data(), (UINT)mSkinnedInputLayout.size() };
//    skinnedSmapPsoDesc.VS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["skinnedShadowVS"]->GetBufferPointer()),
//        mShaders["skinnedShadowVS"]->GetBufferSize()
//    };
//    skinnedSmapPsoDesc.PS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["shadowOpaquePS"]->GetBufferPointer()),
//        mShaders["shadowOpaquePS"]->GetBufferSize()
//    };
//    ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&skinnedSmapPsoDesc, IID_PPV_ARGS(&mPSOs["skinnedShadow_opaque"])));
//
//    //
//    // PSO for debug layer.
//    //
//    D3D12_GRAPHICS_PIPELINE_STATE_DESC debugPsoDesc = opaquePsoDesc;
//    debugPsoDesc.pRootSignature = mRootSignature.Get();
//    debugPsoDesc.VS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["debugVS"]->GetBufferPointer()),
//        mShaders["debugVS"]->GetBufferSize()
//    };
//    debugPsoDesc.PS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["debugPS"]->GetBufferPointer()),
//        mShaders["debugPS"]->GetBufferSize()
//    };
//    ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&debugPsoDesc, IID_PPV_ARGS(&mPSOs["debug"])));
//
//    //
//    // PSO for drawing normals.
//    //
//    D3D12_GRAPHICS_PIPELINE_STATE_DESC drawNormalsPsoDesc = opaquePsoDesc;
//    drawNormalsPsoDesc.VS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["drawNormalsVS"]->GetBufferPointer()),
//        mShaders["drawNormalsVS"]->GetBufferSize()
//    };
//    drawNormalsPsoDesc.PS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["drawNormalsPS"]->GetBufferPointer()),
//        mShaders["drawNormalsPS"]->GetBufferSize()
//    };
//    drawNormalsPsoDesc.RTVFormats[0] = AnimSsao::NormalMapFormat;
//    drawNormalsPsoDesc.SampleDesc.Count = 1;
//    drawNormalsPsoDesc.SampleDesc.Quality = 0;
//    drawNormalsPsoDesc.DSVFormat = mDepthStencilFormat;
//    ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&drawNormalsPsoDesc, IID_PPV_ARGS(&mPSOs["drawNormals"])));
//
//    D3D12_GRAPHICS_PIPELINE_STATE_DESC skinnedDrawNormalsPsoDesc = drawNormalsPsoDesc;
//    skinnedDrawNormalsPsoDesc.InputLayout = { mSkinnedInputLayout.data(), (UINT)mSkinnedInputLayout.size() };
//    skinnedDrawNormalsPsoDesc.VS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["skinnedDrawNormalsVS"]->GetBufferPointer()),
//        mShaders["skinnedDrawNormalsVS"]->GetBufferSize()
//    };
//    skinnedDrawNormalsPsoDesc.PS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["drawNormalsPS"]->GetBufferPointer()),
//        mShaders["drawNormalsPS"]->GetBufferSize()
//    };
//    ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&skinnedDrawNormalsPsoDesc, IID_PPV_ARGS(&mPSOs["skinnedDrawNormals"])));
//
//    //
//    // PSO for SSAO.
//    //
//    D3D12_GRAPHICS_PIPELINE_STATE_DESC ssaoPsoDesc = opaquePsoDesc;
//    ssaoPsoDesc.InputLayout = { nullptr, 0 };
//    ssaoPsoDesc.pRootSignature = mSsaoRootSignature.Get();
//    ssaoPsoDesc.VS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["ssaoVS"]->GetBufferPointer()),
//        mShaders["ssaoVS"]->GetBufferSize()
//    };
//    ssaoPsoDesc.PS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["ssaoPS"]->GetBufferPointer()),
//        mShaders["ssaoPS"]->GetBufferSize()
//    };
//
//    // SSAO effect does not need the depth buffer.
//    ssaoPsoDesc.DepthStencilState.DepthEnable = false;
//    ssaoPsoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO;
//    ssaoPsoDesc.RTVFormats[0] = AnimSsao::AmbientMapFormat;
//    ssaoPsoDesc.SampleDesc.Count = 1;
//    ssaoPsoDesc.SampleDesc.Quality = 0;
//    ssaoPsoDesc.DSVFormat = DXGI_FORMAT_UNKNOWN;
//    ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&ssaoPsoDesc, IID_PPV_ARGS(&mPSOs["ssao"])));
//
//    //
//    // PSO for SSAO blur.
//    //
//    D3D12_GRAPHICS_PIPELINE_STATE_DESC ssaoBlurPsoDesc = ssaoPsoDesc;
//    ssaoBlurPsoDesc.VS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["ssaoBlurVS"]->GetBufferPointer()),
//        mShaders["ssaoBlurVS"]->GetBufferSize()
//    };
//    ssaoBlurPsoDesc.PS =
//    {
//        reinterpret_cast<BYTE*>(mShaders["ssaoBlurPS"]->GetBufferPointer()),
//        mShaders["ssaoBlurPS"]->GetBufferSize()
//    };
//    ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&ssaoBlurPsoDesc, IID_PPV_ARGS(&mPSOs["ssaoBlur"])));
//
//	//
//	// PSO for sky.
//	//
//	D3D12_GRAPHICS_PIPELINE_STATE_DESC skyPsoDesc = opaquePsoDesc;
//
//	// The camera is inside the sky sphere, so just turn off culling.
//	skyPsoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
//
//	// Make sure the depth function is LESS_EQUAL and not just LESS.  
//	// Otherwise, the normalized depth values at z = 1 (NDC) will 
//	// fail the depth test if the depth buffer was cleared to 1.
//	skyPsoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
//	skyPsoDesc.pRootSignature = mRootSignature.Get();
//	skyPsoDesc.VS =
//	{
//		reinterpret_cast<BYTE*>(mShaders["skyVS"]->GetBufferPointer()),
//		mShaders["skyVS"]->GetBufferSize()
//	};
//	skyPsoDesc.PS =
//	{
//		reinterpret_cast<BYTE*>(mShaders["skyPS"]->GetBufferPointer()),
//		mShaders["skyPS"]->GetBufferSize()
//	};
//	ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&skyPsoDesc, IID_PPV_ARGS(&mPSOs["sky"])));
//
//}
//
//void SkinnedMeshApp::BuildFrameResources()
//{
//    for(int i = 0; i < gNumFrameResources; ++i)
//    {
//        mFrameResources.push_back(std::make_unique<AnimFrameResource>(md3dDevice.Get(),
//            2, (UINT)mAllRitems.size(), 
//            1,
//            (UINT)mMaterials.size()));
//    }
//}
//
//void SkinnedMeshApp::BuildMaterials()
//{
//	auto bricks0 = std::make_unique<Material>();
//	bricks0->Name = "bricks0";
//	bricks0->MatCBIndex = 0;
//	bricks0->DiffuseSrvHeapIndex = 0;
//	bricks0->NormalSrvHeapIndex = 1;
//	bricks0->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
//    bricks0->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
//    bricks0->Roughness = 0.3f;
// 
//	auto tile0 = std::make_unique<Material>();
//	tile0->Name = "tile0";
//	tile0->MatCBIndex = 1;
//	tile0->DiffuseSrvHeapIndex = 2;
//	tile0->NormalSrvHeapIndex = 3;
//	tile0->DiffuseAlbedo = XMFLOAT4(0.9f, 0.9f, 0.9f, 1.0f);
//	tile0->FresnelR0 = XMFLOAT3(0.2f, 0.2f, 0.2f);
//	tile0->Roughness = 0.1f;
//
//	auto mirror0 = std::make_unique<Material>();
//	mirror0->Name = "mirror0";
//	mirror0->MatCBIndex = 2;
//	mirror0->DiffuseSrvHeapIndex = 4;
//	mirror0->NormalSrvHeapIndex = 5;
//	mirror0->DiffuseAlbedo = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
//	mirror0->FresnelR0 = XMFLOAT3(0.98f, 0.97f, 0.95f);
//	mirror0->Roughness = 0.1f;
//
//	auto sky = std::make_unique<Material>();
//	sky->Name = "sky";
//	sky->MatCBIndex = 3;
//	sky->DiffuseSrvHeapIndex = 6;
//	sky->NormalSrvHeapIndex = 7;
//	sky->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
//	sky->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
//	sky->Roughness = 1.0f;
//
//	mMaterials["bricks0"] = std::move(bricks0);
//	mMaterials["tile0"] = std::move(tile0);
//	mMaterials["mirror0"] = std::move(mirror0);
//    mMaterials["sky"] = std::move(sky);
//
//    UINT matCBIndex = 4;
//    UINT srvHeapIndex = mSkinnedSrvHeapStart;
//    for(UINT i = 0; i < mSkinnedMats.size(); ++i)
//    {
//        auto mat = std::make_unique<Material>();
//        mat->Name = mSkinnedMats[i].Name;
//        mat->MatCBIndex = matCBIndex++;
//        mat->DiffuseSrvHeapIndex = srvHeapIndex++;
//        mat->NormalSrvHeapIndex = srvHeapIndex++;
//        mat->DiffuseAlbedo = mSkinnedMats[i].DiffuseAlbedo;
//        mat->FresnelR0 = mSkinnedMats[i].FresnelR0;
//        mat->Roughness = mSkinnedMats[i].Roughness;
//
//        mMaterials[mat->Name] = std::move(mat);
//    }
//}
//
//void SkinnedMeshApp::BuildRenderItems()
//{
//	auto skyRitem = std::make_unique<RenderItem>();
//	XMStoreFloat4x4(&skyRitem->World, XMMatrixScaling(5000.0f, 5000.0f, 5000.0f));
//	skyRitem->TexTransform = MathHelper::Identity4x4();
//	skyRitem->ObjCBIndex = 0;
//	skyRitem->Mat = mMaterials["sky"].get();
//	skyRitem->Geo = mGeometries["shapeGeo"].get();
//	skyRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//	skyRitem->IndexCount = skyRitem->Geo->DrawArgs["sphere"].IndexCount;
//	skyRitem->StartIndexLocation = skyRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
//	skyRitem->BaseVertexLocation = skyRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
//
//	mRitemLayer[(int)RenderLayer::Sky].push_back(skyRitem.get());
//	mAllRitems.push_back(std::move(skyRitem));
//    
//    auto quadRitem = std::make_unique<RenderItem>();
//    quadRitem->World = MathHelper::Identity4x4();
//    quadRitem->TexTransform = MathHelper::Identity4x4();
//    quadRitem->ObjCBIndex = 1;
//    quadRitem->Mat = mMaterials["bricks0"].get();
//    quadRitem->Geo = mGeometries["shapeGeo"].get();
//    quadRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//    quadRitem->IndexCount = quadRitem->Geo->DrawArgs["quad"].IndexCount;
//    quadRitem->StartIndexLocation = quadRitem->Geo->DrawArgs["quad"].StartIndexLocation;
//    quadRitem->BaseVertexLocation = quadRitem->Geo->DrawArgs["quad"].BaseVertexLocation;
//
//    mRitemLayer[(int)RenderLayer::Debug].push_back(quadRitem.get());
//    mAllRitems.push_back(std::move(quadRitem));
//    
//	auto boxRitem = std::make_unique<RenderItem>();
//	XMStoreFloat4x4(&boxRitem->World, XMMatrixScaling(2.0f, 1.0f, 2.0f)*XMMatrixTranslation(0.0f, 0.5f, 0.0f));
//	XMStoreFloat4x4(&boxRitem->TexTransform, XMMatrixScaling(1.0f, 1.0f, 1.0f));
//	boxRitem->ObjCBIndex = 2;
//	boxRitem->Mat = mMaterials["bricks0"].get();
//	boxRitem->Geo = mGeometries["shapeGeo"].get();
//	boxRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//	boxRitem->IndexCount = boxRitem->Geo->DrawArgs["box"].IndexCount;
//	boxRitem->StartIndexLocation = boxRitem->Geo->DrawArgs["box"].StartIndexLocation;
//	boxRitem->BaseVertexLocation = boxRitem->Geo->DrawArgs["box"].BaseVertexLocation;
//
//	mRitemLayer[(int)RenderLayer::Opaque].push_back(boxRitem.get());
//	mAllRitems.push_back(std::move(boxRitem));
//
//    auto gridRitem = std::make_unique<RenderItem>();
//    gridRitem->World = MathHelper::Identity4x4();
//	XMStoreFloat4x4(&gridRitem->TexTransform, XMMatrixScaling(8.0f, 8.0f, 1.0f));
//	gridRitem->ObjCBIndex = 3;
//	gridRitem->Mat = mMaterials["tile0"].get();
//	gridRitem->Geo = mGeometries["shapeGeo"].get();
//	gridRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//    gridRitem->IndexCount = gridRitem->Geo->DrawArgs["grid"].IndexCount;
//    gridRitem->StartIndexLocation = gridRitem->Geo->DrawArgs["grid"].StartIndexLocation;
//    gridRitem->BaseVertexLocation = gridRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
//
//	mRitemLayer[(int)RenderLayer::Opaque].push_back(gridRitem.get());
//	mAllRitems.push_back(std::move(gridRitem));
//
//	XMMATRIX brickTexTransform = XMMatrixScaling(1.5f, 2.0f, 1.0f);
//	UINT objCBIndex = 4;
//	for(int i = 0; i < 5; ++i)
//	{
//		auto leftCylRitem = std::make_unique<RenderItem>();
//		auto rightCylRitem = std::make_unique<RenderItem>();
//		auto leftSphereRitem = std::make_unique<RenderItem>();
//		auto rightSphereRitem = std::make_unique<RenderItem>();
//
//		XMMATRIX leftCylWorld = XMMatrixTranslation(-5.0f, 1.5f, -10.0f + i*5.0f);
//		XMMATRIX rightCylWorld = XMMatrixTranslation(+5.0f, 1.5f, -10.0f + i*5.0f);
//
//		XMMATRIX leftSphereWorld = XMMatrixTranslation(-5.0f, 3.5f, -10.0f + i*5.0f);
//		XMMATRIX rightSphereWorld = XMMatrixTranslation(+5.0f, 3.5f, -10.0f + i*5.0f);
//
//		XMStoreFloat4x4(&leftCylRitem->World, rightCylWorld);
//		XMStoreFloat4x4(&leftCylRitem->TexTransform, brickTexTransform);
//		leftCylRitem->ObjCBIndex = objCBIndex++;
//		leftCylRitem->Mat = mMaterials["bricks0"].get();
//		leftCylRitem->Geo = mGeometries["shapeGeo"].get();
//		leftCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//		leftCylRitem->IndexCount = leftCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
//		leftCylRitem->StartIndexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
//		leftCylRitem->BaseVertexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
//
//		XMStoreFloat4x4(&rightCylRitem->World, leftCylWorld);
//		XMStoreFloat4x4(&rightCylRitem->TexTransform, brickTexTransform);
//		rightCylRitem->ObjCBIndex = objCBIndex++;
//		rightCylRitem->Mat = mMaterials["bricks0"].get();
//		rightCylRitem->Geo = mGeometries["shapeGeo"].get();
//		rightCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//		rightCylRitem->IndexCount = rightCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
//		rightCylRitem->StartIndexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
//		rightCylRitem->BaseVertexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
//
//		XMStoreFloat4x4(&leftSphereRitem->World, leftSphereWorld);
//		leftSphereRitem->TexTransform = MathHelper::Identity4x4();
//		leftSphereRitem->ObjCBIndex = objCBIndex++;
//		leftSphereRitem->Mat = mMaterials["mirror0"].get();
//		leftSphereRitem->Geo = mGeometries["shapeGeo"].get();
//		leftSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//		leftSphereRitem->IndexCount = leftSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
//		leftSphereRitem->StartIndexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
//		leftSphereRitem->BaseVertexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
//
//		XMStoreFloat4x4(&rightSphereRitem->World, rightSphereWorld);
//		rightSphereRitem->TexTransform = MathHelper::Identity4x4();
//		rightSphereRitem->ObjCBIndex = objCBIndex++;
//		rightSphereRitem->Mat = mMaterials["mirror0"].get();
//		rightSphereRitem->Geo = mGeometries["shapeGeo"].get();
//		rightSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//		rightSphereRitem->IndexCount = rightSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
//		rightSphereRitem->StartIndexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
//		rightSphereRitem->BaseVertexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
//
//		mRitemLayer[(int)RenderLayer::Opaque].push_back(leftCylRitem.get());
//		mRitemLayer[(int)RenderLayer::Opaque].push_back(rightCylRitem.get());
//		mRitemLayer[(int)RenderLayer::Opaque].push_back(leftSphereRitem.get());
//		mRitemLayer[(int)RenderLayer::Opaque].push_back(rightSphereRitem.get());
//
//		mAllRitems.push_back(std::move(leftCylRitem));
//		mAllRitems.push_back(std::move(rightCylRitem));
//		mAllRitems.push_back(std::move(leftSphereRitem));
//		mAllRitems.push_back(std::move(rightSphereRitem));
//	}
//
//    for(UINT i = 0; i < mSkinnedMats.size(); ++i)
//    {
//        std::string submeshName = "sm_" + std::to_string(i);
//
//        auto ritem = std::make_unique<RenderItem>();
//
//        // Reflect to change coordinate system from the RHS the data was exported out as.
//        XMMATRIX modelScale = XMMatrixScaling(0.05f, 0.05f, -0.05f);
//        XMMATRIX modelRot = XMMatrixRotationY(MathHelper::Pi);
//        XMMATRIX modelOffset = XMMatrixTranslation(0.0f, 0.0f, -5.0f);
//        XMStoreFloat4x4(&ritem->World, modelScale*modelRot*modelOffset);
//
//        ritem->TexTransform = MathHelper::Identity4x4();
//        ritem->ObjCBIndex = objCBIndex++;
//        ritem->Mat = mMaterials[mSkinnedMats[i].Name].get();
//        ritem->Geo = mGeometries[mSkinnedModelFilename].get();
//        ritem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
//        ritem->IndexCount = ritem->Geo->DrawArgs[submeshName].IndexCount;
//        ritem->StartIndexLocation = ritem->Geo->DrawArgs[submeshName].StartIndexLocation;
//        ritem->BaseVertexLocation = ritem->Geo->DrawArgs[submeshName].BaseVertexLocation;
//
//        // All render items for this solider.m3d instance share
//        // the same skinned model instance.
//        ritem->SkinnedCBIndex = 0;
//        ritem->SkinnedModelInst = mSkinnedModelInst.get();
//
//        mRitemLayer[(int)RenderLayer::SkinnedOpaque].push_back(ritem.get());
//        mAllRitems.push_back(std::move(ritem));
//    }
//}
//
//void SkinnedMeshApp::DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems)
//{
//    UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
//    UINT skinnedCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(SkinnedConstants));
//
//	auto objectCB = mCurrFrameResource->ObjectCB->Resource();
//    auto skinnedCB = mCurrFrameResource->SkinnedCB->Resource();
//
//    // For each render item...
//    for(size_t i = 0; i < ritems.size(); ++i)
//    {
//        auto ri = ritems[i];
//
//        cmdList->IASetVertexBuffers(0, 1, &ri->Geo->VertexBufferView());
//        cmdList->IASetIndexBuffer(&ri->Geo->IndexBufferView());
//        cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
//
//        D3D12_GPU_VIRTUAL_ADDRESS objCBAddress = objectCB->GetGPUVirtualAddress() + ri->ObjCBIndex*objCBByteSize;
//
//		cmdList->SetGraphicsRootConstantBufferView(0, objCBAddress);
//
//        if(ri->SkinnedModelInst != nullptr)
//        {
//            D3D12_GPU_VIRTUAL_ADDRESS skinnedCBAddress = skinnedCB->GetGPUVirtualAddress() + ri->SkinnedCBIndex*skinnedCBByteSize;
//            cmdList->SetGraphicsRootConstantBufferView(1, skinnedCBAddress);
//        }
//        else
//        {
//            cmdList->SetGraphicsRootConstantBufferView(1, 0);
//        }
//
//        cmdList->DrawIndexedInstanced(ri->IndexCount, 1, ri->StartIndexLocation, ri->BaseVertexLocation, 0);
//    }
//}
//
//void SkinnedMeshApp::DrawSceneToShadowMap()
//{
//    mCommandList->RSSetViewports(1, &mShadowMap->Viewport());
//    mCommandList->RSSetScissorRects(1, &mShadowMap->ScissorRect());
//
//    // Change to DEPTH_WRITE.
//    mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mShadowMap->Resource(),
//        D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE));
//
//    // Clear the back buffer and depth buffer.
//    mCommandList->ClearDepthStencilView(mShadowMap->Dsv(), 
//        D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
//
//    // Specify the buffers we are going to render to.
//    mCommandList->OMSetRenderTargets(0, nullptr, false, &mShadowMap->Dsv());
//
//    // Bind the pass constant buffer for the shadow map pass.
//    UINT passCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(PassConstants));
//    auto passCB = mCurrFrameResource->PassCB->Resource();
//    D3D12_GPU_VIRTUAL_ADDRESS passCBAddress = passCB->GetGPUVirtualAddress() + 1*passCBByteSize;
//    mCommandList->SetGraphicsRootConstantBufferView(2, passCBAddress);
//
//    mCommandList->SetPipelineState(mPSOs["shadow_opaque"].Get());
//    DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
//
//    mCommandList->SetPipelineState(mPSOs["skinnedShadow_opaque"].Get());
//    DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::SkinnedOpaque]);
//
//    // Change back to GENERIC_READ so we can read the texture in a shader.
//    mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mShadowMap->Resource(),
//        D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ));
//}
// 
//void SkinnedMeshApp::DrawNormalsAndDepth()
//{
//	mCommandList->RSSetViewports(1, &mScreenViewport);
//    mCommandList->RSSetScissorRects(1, &mScissorRect);
//
//	auto normalMap = mSsao->NormalMap();
//	auto normalMapRtv = mSsao->NormalMapRtv();
//	
//    // Change to RENDER_TARGET.
//    mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(normalMap,
//        D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET));
//
//	// Clear the screen normal map and depth buffer.
//	float clearValue[] = {0.0f, 0.0f, 1.0f, 0.0f};
//    mCommandList->ClearRenderTargetView(normalMapRtv, clearValue, 0, nullptr);
//    mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
//
//	// Specify the buffers we are going to render to.
//    mCommandList->OMSetRenderTargets(1, &normalMapRtv, true, &DepthStencilView());
//
//    // Bind the constant buffer for this pass.
//    auto passCB = mCurrFrameResource->PassCB->Resource();
//    mCommandList->SetGraphicsRootConstantBufferView(2, passCB->GetGPUVirtualAddress());
//
//    mCommandList->SetPipelineState(mPSOs["drawNormals"].Get());
//    DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
//
//    mCommandList->SetPipelineState(mPSOs["skinnedDrawNormals"].Get());
//    DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::SkinnedOpaque]);
//
//    // Change back to GENERIC_READ so we can read the texture in a shader.
//    mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(normalMap,
//        D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
//}
//CD3DX12_CPU_DESCRIPTOR_HANDLE SkinnedMeshApp::GetCpuSrv(int index)const
//{
//    auto srv = CD3DX12_CPU_DESCRIPTOR_HANDLE(mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
//    srv.Offset(index, mCbvSrvUavDescriptorSize);
//    return srv;
//}
//
//CD3DX12_GPU_DESCRIPTOR_HANDLE SkinnedMeshApp::GetGpuSrv(int index)const
//{
//    auto srv = CD3DX12_GPU_DESCRIPTOR_HANDLE(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
//    srv.Offset(index, mCbvSrvUavDescriptorSize);
//    return srv;
//}
//
//CD3DX12_CPU_DESCRIPTOR_HANDLE SkinnedMeshApp::GetDsv(int index)const
//{
//    auto dsv = CD3DX12_CPU_DESCRIPTOR_HANDLE(mDsvHeap->GetCPUDescriptorHandleForHeapStart());
//    dsv.Offset(index, mDsvDescriptorSize);
//    return dsv;
//}
//
//CD3DX12_CPU_DESCRIPTOR_HANDLE SkinnedMeshApp::GetRtv(int index)const
//{
//    auto rtv = CD3DX12_CPU_DESCRIPTOR_HANDLE(mRtvHeap->GetCPUDescriptorHandleForHeapStart());
//    rtv.Offset(index, mRtvDescriptorSize);
//    return rtv;
//}
//
//std::array<const CD3DX12_STATIC_SAMPLER_DESC, 7> SkinnedMeshApp::GetStaticSamplers()
//{
//	// Applications usually only need a handful of samplers.  So just define them all up front
//	// and keep them available as part of the root signature.  
//
//	const CD3DX12_STATIC_SAMPLER_DESC pointWrap(
//		0, // shaderRegister
//		D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
//
//	const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
//		1, // shaderRegister
//		D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
//
//	const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
//		2, // shaderRegister
//		D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
//
//	const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
//		3, // shaderRegister
//		D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
//
//	const CD3DX12_STATIC_SAMPLER_DESC anisotropicWrap(
//		4, // shaderRegister
//		D3D12_FILTER_ANISOTROPIC, // filter
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
//		D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressW
//		0.0f,                             // mipLODBias
//		8);                               // maxAnisotropy
//
//	const CD3DX12_STATIC_SAMPLER_DESC anisotropicClamp(
//		5, // shaderRegister
//		D3D12_FILTER_ANISOTROPIC, // filter
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
//		D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressW
//		0.0f,                              // mipLODBias
//		8);                                // maxAnisotropy
//
//    const CD3DX12_STATIC_SAMPLER_DESC shadow(
//        6, // shaderRegister
//        D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT, // filter
//        D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressU
//        D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressV
//        D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressW
//        0.0f,                               // mipLODBias
//        16,                                 // maxAnisotropy
//        D3D12_COMPARISON_FUNC_LESS_EQUAL,
//        D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK);
//
//	return { 
//		pointWrap, pointClamp,
//		linearWrap, linearClamp, 
//		anisotropicWrap, anisotropicClamp,
//        shadow 
//    };
//}
//
